package com.xy.biz.xd.service.impl;

import com.xy.biz.fd.client.DocumentClient;
import com.xy.biz.fd.client.DocumentCodePoolClient;
import com.xy.biz.fd.client.DocumentCodeRuleClient;
import com.xy.biz.fd.domain.req.SaveDocumentCodePoolRequest;
import com.xy.biz.fd.domain.req.document.SaveDocumentRequest;
import com.xy.biz.fd.domain.req.documentCode.GetDocumentCodeRuleRequest;
import com.xy.biz.fd.domain.resp.GetDocumentCodeRuleResponse1;
import com.xy.biz.mc.client.MessagePushClient;
import com.xy.biz.mc.domain.Message;
import com.xy.biz.mc.domain.consts.MessageTypeConstant;
import com.xy.biz.mc.domain.req.MessagePushRequest;
import com.xy.biz.xd.domain.bo.*;
import com.xy.biz.xd.domain.converter.DocumentFlowNewAndModifyConverter;
import com.xy.biz.xd.domain.enums.DocumentFlowBatchTypeEnum;
import com.xy.biz.xd.domain.query.DocumentReleaseQuery;
import com.xy.biz.xd.domain.req.*;
import com.xy.biz.xd.manager.*;
import com.xy.biz.xd.service.DocumentFlowNewService;
import com.xy.lang.domain.Result;
import com.xy.lang.domain.tuples.Triple;
import com.xy.lang.util.ResultUtils;
import com.xy.tool.context.UserContextHolder;
import com.xy.tool.json.JsonUtils;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.xy.biz.xd.domain.bo.DocumentFlowConstants.*;

@Service
public class DocumentFlowNewServiceImpl extends AbstractDocumentFlowNewAndModifyServiceImpl implements DocumentFlowNewService {

    @Autowired
    private DocumentClient documentClient;
    @Autowired
    private MessagePushClient messagePushClient;
    @Autowired
    private DocumentReleaseManager documentReleaseManager;
    @Autowired
    private DocumentCodePoolClient documentCodePoolClient;
    @Autowired
    private DocumentCodeRuleClient documentCodeRuleClient;
    @Autowired
    private DocumentFlowHandleManager documentFlowHandleManager;
    @Autowired
    private DocumentFlowServiceSupport documentFlowServiceSupport;
    @Autowired
    private DocumentReleaseCheckManager documentReleaseCheckManager;
    @Autowired
    private DocumentFlowNewAndModifyManager documentFlowNewAndModifyManager;
    private final String type = "新增";

    @Override
    protected String getType() {
        return type;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<?> saveDocumentFlow(ApplyDocumentFlowNewRequest request) {
        if(Objects.isNull(UserContextHolder.getUserGroupId())){
            return Result.ofBadRequest("用户部门缺失！");
        }
        List<DocumentFlowNewAndModifyBO> documentFlowNewAndModifyBOList = DocumentFlowNewAndModifyConverter.toBOList(request);
        DocumentFlowNewAndModifyBO documentFlowNewBO = buildNewDocumentFlowBO(documentFlowNewAndModifyBOList, FLOW_TYPE_NEW);
        Task task = documentFlowServiceSupport.startFirstTask(documentFlowNewBO, PROCESS_NEW_FLOW, documentFlowNewBO.getDocumentManagerUserId());
//        Task task = documentFlowServiceSupport.startFirstTask2(documentFlowNewBO, PROCESS_NEW_FLOW, documentFlowNewBO.getDocumentManagerUserIdList());
        String foreignKey = task.getProcessInstanceId();
        documentFlowNewBO.setForeignKey(foreignKey);
        int row = documentFlowNewAndModifyManager.saveAllDocumentFlowNewAndModify(documentFlowNewAndModifyBOList);
        if (row > 0) {
//            List<SaveDocumentCodePoolRequest> documentCodePoolRequestList = new ArrayList<>();
//            LocalDateTime now = LocalDateTime.now();
//            documentFlowNewAndModifyBOList.forEach(e -> {
//                documentCodePoolRequestList.add(
//                        SaveDocumentCodePoolRequest
//                                .builder()
//                                .reuseFlag(false)
//                                .updateTime(now)
//                                .documentCode(e.getDocumentCode())
//                                .build());
//            });
//            Integer results = ResultUtils.get(documentCodePoolClient.updateAllDocumentCodePoolByCode(documentCodePoolRequestList));
//            if (results <= 0) {
//                throw new RuntimeException("Description Failed to modify the document code pool reuseFlag!");
//            }

            //定义消息内容
            List<ApplyDocumentFlowNewRequest.DocumentFlowInfo> documentFlowInfoList = request.getDocumentFlowInfoList();
            Map<String, Long> documentCodeMap = documentFlowInfoList.stream()
                    .collect(Collectors.toMap(ApplyDocumentFlowNewRequest.DocumentFlowInfo::getDocumentCode
                            , ApplyDocumentFlowNewRequest.DocumentFlowInfo::getDocumentId));
            //锁定原文档
            Integer rows = ResultUtils.get(documentClient.updateDocumentByIds(SaveDocumentRequest.builder().documentFlowLock(true).documentIds(new ArrayList<>(documentCodeMap.values())).build()));
            if (rows < 1) {
                return Result.fail("", "原文件不存在！");
            }
            LocalDateTime now = LocalDateTime.now();
            if (documentFlowInfoList.size() > 1) {
                List<SaveDocumentCodePoolRequest> documentCodePoolRequestList = new ArrayList<>();
                documentFlowInfoList.forEach(e -> documentCodePoolRequestList.add(SaveDocumentCodePoolRequest
                        .builder()
                        .documentCode(e.getDocumentCode())
                        .reuseFlag(true)
                        .updateTime(now)
                        .build()));
                documentCodePoolClient.updateAllDocumentCodePoolByCode(documentCodePoolRequestList);
            } else {
                SaveDocumentCodePoolRequest req = SaveDocumentCodePoolRequest.builder()
                        .documentCode(documentFlowNewBO.getDocumentCode())
                        .reuseFlag(true)
                        .updateTime(now)
                        .build();
                documentCodePoolClient.updateDocumentCodePool(req);
            }

            Message build = Message.builder()
                    .type(MessageTypeConstant.TYPE_FLOW)
                    .data(1)
                    .path(MessageTypeConstant.FLOW_LIST)
                    .remark("新增流程-申请审批")
                    .build();
            //发送消息
            messagePushClient.send(MessagePushRequest.builder()
                    .data(JsonUtils.toJson(build).getBytes())
                    .dataType(0)
                    .expiredSeconds(0L)
                    .toId(request.getDocumentManagerUserId())
                    .offlineFlag(true).build());
//            request.getDocumentManagerUserIdList().forEach(e -> {
//                messagePushClient.send(MessagePushRequest.builder()
//                        .data(JsonUtils.toJson(build).getBytes())
//                        .dataType(0)
//                        .expiredSeconds(0L)
//                        .toId(e)
//                        .offlineFlag(true).build());
//            });
        }
        return Result.success(documentFlowNewBO.getDocumentFlowId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<?> uploadDocumentFlow(UploadDocumentFlowNewRequest request) {
        DocumentFlowNewAndModifyBO documentFlowNewAndModifyBO = documentFlowNewAndModifyManager.getDocumentFlowNewAndModify(request.getDocumentFlowId());
        List<UploadDocumentFlowNewRequest.DocumentFlowInfo> documentFlowInfoList = request.getDocumentFlowInfoList();
        if (Objects.isNull(documentFlowNewAndModifyBO) || CollectionUtils.isEmpty(documentFlowInfoList)) {
            return Result.ofNotFound(String.valueOf(request.getDocumentFlowId()));
        }
        Map<String, Long> documentCodeMap = new HashMap<>();
        if (Objects.equals(HANDLE_RESULT_ACCEPT, request.getResult())) {
            documentCodeMap = documentFlowInfoList.stream().collect(Collectors.toMap(UploadDocumentFlowNewRequest.DocumentFlowInfo::getDocumentCode, UploadDocumentFlowNewRequest.DocumentFlowInfo::getDocumentId));
            //锁定原文档
            Integer rows = ResultUtils.get(documentClient.updateDocumentByIds(SaveDocumentRequest.builder().documentFlowLock(true).documentIds(new ArrayList<>(documentCodeMap.values())).build()));
            if (rows < 1) {
                return Result.fail("", "原文件不存在！");
            }
            DocumentFlowHandleBO documentFlowHandleBO = DocumentFlowHandleBO.build(
                    documentFlowNewAndModifyBO,
                    UserContextHolder.getUserId(),
                    PHASE_UPLOAD,
                    HANDLE_RESULT_ACCEPT, request.getOpinion());
            documentFlowHandleManager.saveAllDocumentFlowHandle(Collections.singletonList(documentFlowHandleBO));
            documentFlowNewAndModifyBO.setPhase(PHASE_EDIT);
            documentFlowServiceSupport.gotoNextTask(documentFlowNewAndModifyBO, request.getEditUserId(), request.getResult());
        } else {
            DocumentFlowHandleBO documentFlowHandleBO = DocumentFlowHandleBO.build(
                    documentFlowNewAndModifyBO,
                    UserContextHolder.getUserId(),
                    PHASE_UPLOAD,
                    HANDLE_RESULT_REJECT, request.getOpinion());
            documentFlowHandleManager.saveAllDocumentFlowHandle(Collections.singletonList(documentFlowHandleBO));
            documentFlowNewAndModifyBO.setPhase(PHASE_REJECT);
            documentFlowServiceSupport.gotoNextTask(documentFlowNewAndModifyBO, null, request.getResult());

            GetDocumentCodeRuleResponse1 response1 = ResultUtils.get(documentCodeRuleClient.getCodeInfo(GetDocumentCodeRuleRequest.builder().code(documentFlowNewAndModifyBO.getDocumentCode()).build()));
            if (Objects.isNull(response1)) {
                return Result.fail();
            }
            LocalDateTime now = LocalDateTime.now();
            if (documentFlowInfoList.size() > 1) {
                List<SaveDocumentCodePoolRequest> documentCodePoolRequestList = new ArrayList<>();
                documentFlowInfoList.forEach(e -> documentCodePoolRequestList.add(SaveDocumentCodePoolRequest
                        .builder()
                        .documentCode(e.getDocumentCode())
                        .reuseFlag(true)
                        .updateTime(now)
                        .build()));
                documentCodePoolClient.updateAllDocumentCodePoolByCode(documentCodePoolRequestList);
            } else {
                SaveDocumentCodePoolRequest req = SaveDocumentCodePoolRequest.builder()
                        .documentCode(documentFlowNewAndModifyBO.getDocumentCode())
                        .reuseFlag(true)
                        .updateTime(now)
                        .build();
                documentCodePoolClient.updateDocumentCodePool(req);
            }
        }
        List<DocumentFlowNewAndModifyBO> documentFlowNewAndModifyBOList = buildUploadDocumentFlowNewAndModifyBO(documentFlowNewAndModifyBO, documentCodeMap, Collections.emptyMap());
        int row = documentFlowNewAndModifyManager.updateAllDocumentFlowNewAndModify(documentFlowNewAndModifyBOList);
        if (row > 0) {
            //定义消息内容
            Message message = Message.builder()
                    .type(MessageTypeConstant.TYPE_FLOW)
                    .path(MessageTypeConstant.FLOW_LIST)
                    .build();
            //定义发送给谁
            Long toId;
            //通过的信息
            if (Objects.equals(HANDLE_RESULT_ACCEPT, request.getResult())) {
                message.setRemark("新增流程-文件编辑");
                message.setData(1);
                toId = request.getEditUserId();
            } else {//不通过的信息
                message.setRemark("新增流程-文件上传管理拒绝申请");
                message.setData(0);
                //获取申请人
                toId = getApplyUserId(request.getDocumentFlowId(), PHASE_APPLY);
            }
            //发送消息
            sendMessage(message, toId);
        }
        return Result.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<?> releaseDocumentFlow(ReleaseDocumentFlowNewRequest request) {
        DocumentFlowNewAndModifyBO documentFlowBO = documentFlowNewAndModifyManager.getDocumentFlowNewAndModify(request.getDocumentFlowId());
        if (Objects.isNull(documentFlowBO)) {
            return Result.ofNotFound(String.valueOf(request.getDocumentFlowId()));
        }
        Integer batchType = documentFlowBO.getBatchType();
        Result<Triple<List<DocumentFlowNewAndModifyBO>, List<Long>, List<Long>>> result;
        if (!(result = saveDocumentReleaseList(request, documentFlowBO, batchType)).wasSuccess()) {
            return result;
        }
        Triple<List<DocumentFlowNewAndModifyBO>, List<Long>, List<Long>> triple = ResultUtils.get(result);
        if (batchType.equals(DocumentFlowBatchTypeEnum.UNBATCH.getCode())) {
            //完善新发行文档信息
            documentClient.updateDocument(buildRequest(documentFlowBO, request.getOpinion()));
        } else {
            List<SaveDocumentRequest> requestList = new ArrayList<>();
            triple.getValue1().forEach(e -> requestList.add(buildRequest(e, request.getOpinion())));
            documentClient.updateAllDocument(requestList);
        }
        //完善培训信息
        documentFlowBO.setTrainFlag(request.getTrainFlag());
        documentFlowBO.setTrainCheckStatus(0);
        documentFlowBO.setTrainerUserId(request.getTrainerUserId());
        documentFlowBO.setPhase(PHASE_RELEASE);
        int row = documentFlowNewAndModifyManager.updateDocumentFlowNewAndModify(documentFlowBO);
        if (row > 0) {
            //定义消息内容
            Message message = Message.builder()
                    .type(MessageTypeConstant.TYPE_FLOW)
                    .data(0)
                    .remark("新增一条新的放行文件-去签收")
                    .path(MessageTypeConstant.DOCUMENT_RELEASE_CHECK)
                    .build();
            //发送消息
            Set<Long> userIdSet = buildMessageReceiveUserIdCollection(triple.getValue2(), triple.getValue3());
            for (Long userId : userIdSet) {
                sendMessage(message, userId);
            }
        }
        return Result.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<?> updateEffectDate(UpdateDocumentFlowRequest request) {
        Set<Long> collect1 = documentReleaseManager.listDocumentReleaseByDocumentCode(request.getDocumentCode()).stream().map(DocumentReleaseBO::getDocumentReleaseId).collect(Collectors.toSet());
        DocumentReleaseBO build = DocumentReleaseBO.builder().documentReleaseIdS(collect1).effectDate(request.getEffectDate()).build();
        int row = documentReleaseManager.updateDocumentReleaseEffectDateById(build);
        if (row > 0) {
            //查找签收人员列表
            List<DocumentReleaseBO> documentReleaseBOS = documentReleaseManager.listDocumentRelease(DocumentReleaseQuery.max()
                    .documentId(request.getDocumentId()).build());
            Set<Long> collect = documentReleaseBOS.stream().map(DocumentReleaseBO::getDocumentReleaseId).collect(Collectors.toSet());
            documentReleaseCheckManager.deleteDocumentReleaseCheckByDocumentReleaseId(collect);
        }
        return Result.success();
    }
}
